oa.view.rf.memory = {
    /**
     * Render the structure of a memory grid and fill it.
     * Can be used for matching binary standard problems with their answer
     * or for matching natural numbers with corresponding visualizations
     * or for matching proper fractions with corresponding visualizations
     * or for matching equivalent fractions.
     * 
     * @author Gerd Wagner
     * @param {array} apl  A List of arithmetic problems.
     */
    render : function (apl) {
      var nmrOfGridCells = apl.length*2,
          rB = document.getElementById("renderBox"),
          memoryGridEl = document.createElement("table"),
          rowEl=null, cellEl=null, el=null;
      memoryGridEl.setAttribute("id", "memoryGrid");
      rB.appendChild( memoryGridEl);
      oa.rf.memory.computeGridSize( nmrOfGridCells);
      for (var row=1; row <= oa.rf.memory.height; row++) {
        rowEl = document.createElement("tr");        
        for (var col=1; col <= oa.rf.memory.width; col++) {
          cellEl = document.createElement("td");
          cellEl.setAttribute("class", "card");
          cellEl.addEventListener("click", oa.view.rf.memory.handleClickCardEvent, false);
          el = document.createElement("div");  // dom.createDiv("","cardContent");
          cellEl.appendChild( el); 
          rowEl.appendChild( cellEl); 
        }
        memoryGridEl.appendChild( rowEl); 
      }
      document.removeEventListener("keypress", oa.view.handleKeyPressEvents, true);
    },
    /**
     * Fill an already rendered problem structure with values 
     * 
     * @author Gerd Wagner
     * @param {array} apl  A List of arithmetic problems.
     */
    fill : function (apl, rfparams) {
      var cards = new Array(),
          rows = document.getElementById("memoryGrid").querySelectorAll("tr"),
          cells = [],
          n = oa.currentProblems.length,  // number of problems
          mode = 0,
          ap, k;
      if (rfparams && 'memoryMode' in rfparams) {
        mode = rfparams.memoryMode;
      }
      for (var i=0; i < n; i++) {
        ap = oa.currentProblems[i];
        cards[i] = new Object();
        cards[i+n] = new Object();
        cards[i].pair = i;
        cards[i].value = ap.result;
        cards[i].content = ap.operands[0] + oa.view.operatorSymbols[ap.type.operators[0]-1] + ap.operands[1];
        cards[i+n].pair = i;
        cards[i+n].value = ap.result;
        cards[i+n].content = ap.result;
      }
      util.shuffle( cards); 
      for (var i=0; i < oa.rf.memory.height; i++) {
        cells = rows[i].querySelectorAll("td");
        for (var j=0; j < oa.rf.memory.width; j++) {
          k = i * oa.rf.memory.width + j;
          cells[j].setAttribute("data-pair", cards[k].pair); 
          cells[j].setAttribute("data-value", cards[k].value); 
          cells[j].firstChild.innerHTML = cards[k].content; 
          switch (mode) {
          case oa.MemoryModeEL.allValuesVisible:
            if (!util.containsArithmeticOperator( cells[j].firstChild.innerHTML)) {
              cells[j].firstChild.classList.add("disclosed");
            }
            break;
          case oa.MemoryModeEL.allExpressionsVisible:
            if (util.containsArithmeticOperator( cells[j].firstChild.innerHTML)) {
              cells[j].firstChild.classList.add("disclosed");
            }
            break;
          case oa.MemoryModeEL.randomSelectionVisible:
            if (util.randomInt(0,1)) {
              cells[j].firstChild.classList.add("disclosed");
            }
            break;
          }
        }
      }
    },
    /**
     * Event handler for clicking a card
     * 
     * @author Gerd Wagner
     */
    handleClickCardEvent : function (e) {
      var c1,c2;
      var cardEl = e.currentTarget,
          cardContentEl = cardEl.firstChild,
          ccl = cardContentEl.classList;
          card1 = new Object(),
          card2 = new Object();
      // not necessary for found cards, they don't have an event listener
      if (ccl.contains("selected")) return; 
      else cardContentEl.classList.add("selected");
      if (oa.rf.memory.selectedCards === 0) {
        if (!ccl.contains("disclosed")) cardContentEl.style.visibility = "visible";
        oa.rf.memory.selectedCards++;
        oa.rf.memory.firstCardEl = cardEl;
      } else {
        if (!ccl.contains("disclosed")) cardContentEl.style.visibility = "visible";
        oa.rf.memory.secondCardEl = cardEl;     
        oa.rf.memory.selectedCards = 0;
        c1 = oa.rf.memory.firstCardEl;
        card1.pairNo = c1.getAttribute("data-pair");
        card1.value = c1.getAttribute("data-value");
        card1.content = c1.firstChild.innerHTML;
        c2 = oa.rf.memory.secondCardEl;
        card2.pairNo = c2.getAttribute("data-pair");
        card2.value = c2.getAttribute("data-value");
        card2.content = c2.firstChild.innerHTML;
        if (oa.rf.memory.isValidCardPair( card1, card2)) {
          oa.exerciseProblemCounter++;
          c1.removeEventListener("click", oa.view.rf.memory.handleClickCardEvent, false); 
          c2.removeEventListener("click", oa.view.rf.memory.handleClickCardEvent, false); 
          c1.firstChild.classList.add("paired");
          c1.firstChild.style.backgroundColor = oa.view.backgroundColors[c1.getAttribute("data-pair")%10];  
          c2.firstChild.classList.add("paired");
          c2.firstChild.style.backgroundColor = oa.view.backgroundColors[c1.getAttribute("data-pair")%10];
          if (oa.exerciseProblemCounter > oa.currentExercise.numberOfProblems) {
            oa.view.showSmilingAri();
            window.setTimeout( oa.ctrl.continueCurrentLearningUnit, 2000);
          }
        } else {
          window.setTimeout( oa.view.rf.memory.hideBothCards, 1000);
        }
      } 
    },
    hideBothCards : function () {
      var c1 = oa.rf.memory.firstCardEl,
          c2 = oa.rf.memory.secondCardEl;
      c1.firstChild.classList.remove("selected");
      c2.firstChild.classList.remove("selected");
      // hide cards only if they are not disclosed
      if (!c1.firstChild.classList.contains("disclosed")) c1.firstChild.style.visibility = "hidden"; 
      if (!c2.firstChild.classList.contains("disclosed")) c2.firstChild.style.visibility = "hidden"; 
    }
};